/*
 * Copyright the original author or authors.
 * 
 * Licensed under the MOZILLA PUBLIC LICENSE, Version 1.1 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * 
 *	  http://www.mozilla.org/MPL/MPL-1.1.html
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.googlecode.milib.data {
	import com.googlecode.milib.base.MLBroadcastClass;
	import com.googlecode.milib.display.ui.scroller.IScrollable;
	import com.googlecode.milib.service.singleton.KeyboardService;
	import com.googlecode.milib.util.MLArrayUtil;

	import flash.debugger.enterDebugger;

	/**
	 * @author Marek Brun
	 */
	public class ScrollableArray extends MLBroadcastClass implements IScrollable {

		public function get event_ScrollChanged():String { return 'ScrollChanged'; }
		
		private var scrollScope : Number;
		private var arr : Array;
		private var scroll :Number;
			
		public function ScrollableArray(arr:Array=null, scrollScope:Number=4) {
			this.arr=arr==null ? [] : arr.concat();
			this.scrollScope=scrollScope;
			scroll=0;
			
		}
		
		public function setScrollScope(newScrollScope:Number):void {
			if(scrollScope==Math.round(newScrollScope)){ return; }
			scrollScope=Math.max(1, Math.min(Infinity, Math.round(newScrollScope)));
			scroll=Math.max(0, Math.min(scroll, getMaxScroll()));
			if(scroll<0){ scroll=0; }
			broadcastEvent(event_ScrollChanged);
		}
		
		public function setNewArray(arr:Array):void {
			this.arr=arr;
			var orgScrollScope:Number=scrollScope;
			scrollScope=NaN;
			setScrollScope(orgScrollScope);
			broadcastEvent(event_ScrollChanged);
		}
		
		public function getScroll():Number {
			var maxScroll:Number=getMaxScroll();
			if(maxScroll>0 && scroll>0){
				return scroll/maxScroll;
			}else{
				return 0;
			}
		}
		
		public function getScrollUnits():uint {
			return Math.round(getScroll()*getMaxScroll());
		}
		
		public function setScroll(newScroll:Number):void {
			if(isNaN(newScroll)){
				throw new Error('New scroll can\'t be NaN');
			}
//			if(KeyboardService.getInstance().getIsKeyDown(KeyboardService.KEY_CTRL) && newScroll==0) {
//				enterDebugger();
//				//dbg.log('setScroll(' + newScroll+ ')');
//			}
			//if(scroll==Math.round(newScroll*getMaxScroll())){ return; } 
			
			scroll=Math.max(0, Math.min(getMaxScroll(), Math.round(newScroll*getMaxScroll())));
			
			broadcastEvent(event_ScrollChanged);
		}
		
		public function setScrollByUnit(scrollUnits:uint):void {
			setScroll(scrollUnits/getMaxScroll());
		}
		
		public function setScrollByOneUnit(isUp:Boolean):void {
			if(!isUp && getScrollUnits()-1<0){ return; }
			setScrollByUnit(isUp ? getScrollUnits()+1 : getScrollUnits()-1);
		}
		
		public function getCurrentArray():Array {
			if(arr.length<scrollScope){ return arr.concat(); }
			var currArr:Array=[];
			var scrollEnd:Number=scroll+scrollScope;
			for(var i:uint=scroll;i<scrollEnd;i++){
				currArr.push(arr[i]);
			}
			return currArr;
		}
		
		public function getScrollScope():Number {
			return scrollScope;
		}
		
		public function getMaxScroll():Number {
			return arr.length-scrollScope;
		}
		
		public function getCurrentArrayElementByNumber(num:Number) : Object {
			return arr[scroll+num];
		}
		
		public function getBaseNumberByListNumber(num:Number):Number{
			return scroll+num;
		}
		
		public function push(value:*):void {
			arr.push(value);
			broadcastEvent(event_ScrollChanged);
		}
		
		public function remove(value:*):Boolean {
			if(MLArrayUtil.remove(arr, value)){
				broadcastEvent(event_ScrollChanged);
				return true;
			}
			return false;
		}
		
		public function getBaseArrayNumByScrollArrayNum(num:Number):Number { return scroll+num; }
		public function getBaseArrayElementByScrollArrayNum(num:Number):Object {
			return arr[scroll+num];
		}
		public function getBaseArrayLength():Number { return arr.length; }
		public function getBaseArray():Array { return arr.concat(); }
		public function getBaseArrayNoCopy():Array { return arr; }
		
		
		public function getVisibleToTotal():Number {
			return scrollScope/arr.length;
		}
	}
}
